package com.huayun.code.core.jdbc;

import com.huayun.code.core.extractor.ITableExtractor;
import com.huayun.code.core.extractor.JavaType;
import com.huayun.code.core.extractor.JdbcType;
import com.huayun.code.core.model.Column;
import com.huayun.code.core.model.Table;
import com.huayun.code.core.utils.ConfigUtils;
import com.huayun.code.core.utils.NameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Component
public class JdbcTableExtractor implements ITableExtractor {

    @Autowired
    private ConfigUtils configUtils;

    @Autowired
    private DataSource dataSource;

    private static final Logger LOG = LoggerFactory.getLogger(JdbcTableExtractor.class);

    @Override
    public Table getTable(String tableName) {
        Connection conn = null;
        Table t = null;
        try {
            conn = dataSource.getConnection();
            String catalog = configUtils.getCatalog();
            DatabaseMetaData metaData = conn.getMetaData();
            String[] types = new String[]{"TABLE", "VIEW"};
            LOG.debug("catalog:{} tableName:{}", catalog, tableName);
            ResultSet tables = metaData.getTables(catalog, null, tableName, types);
            while (tables.next()) {
                t = new Table();
                String name = tables.getString("TABLE_NAME");
                String type = tables.getString("TABLE_TYPE");
                String comment = tables.getString("REMARKS");
                t.setName(name);
                t.setClazzName(NameUtils.getModelName(name));
                t.setCamelClazzName(StringUtils.uncapitalize(t.getClazzName()));
                t.setType(type);
                t.setComment(comment);

                LOG.debug("数据库CATALOG:{}", tables.getString("TABLE_CAT"));
                LOG.debug("数据库SCHEMA:{}", tables.getString("TABLE_SCHEM"));

                ResultSet columns = metaData.getColumns(catalog, null, name, null);
                List<Column> cols = new ArrayList<>();
                while (columns.next()) {
                    String columnName = columns.getString("COLUMN_NAME");
                    int columnType = columns.getInt("DATA_TYPE");
                    String columnTypeName = columns.getString("TYPE_NAME");
                    String columnComment = columns.getString("REMARKS");
                    int columnSize = columns.getInt("COLUMN_SIZE");
                    String defaultValue = columns.getString("COLUMN_DEF");
                    String isAutoIncrement = columns.getString("IS_AUTOINCREMENT");
                    int decimalDigits = columns.getInt("DECIMAL_DIGITS");
                    String isNullable = columns.getString("IS_NULLABLE");
                    Column col = new Column();
                    col.setName(columnName);
                    col.setFieldName(NameUtils.getFieldName(columnName));
                    col.setCapitalizeFieldName(NameUtils.getCapitalizeFieldName(NameUtils.getFieldName(columnName)));
                    col.setGetter(NameUtils.getter(columnName));
                    col.setSetter(NameUtils.setter(columnName));
                    col.setJdbcType(columnType);
                    JdbcType jdbcType = JdbcType.forCode(columnType);
                    col.setJdbcTypeName(jdbcType.name());
                    col.setColumnTypeName(columnTypeName);
                    if (jdbcType == JdbcType.DECIMAL) {
                        // 没有小数
                        if (decimalDigits == 0) {
                            if (columnSize > 1) {
                                col.setJavaType(Long.class);
                            } else {
                                if (StringUtils.startsWithIgnoreCase(columnName, "if_")) {
                                    col.setJavaType(Boolean.class);
                                } else {
                                    col.setJavaType(Integer.class);
                                }
                            }
                        } else {
                            col.setJavaType(JavaType.jdbcType2JavaType(jdbcType));
                        }
                    } else {
                        col.setJavaType(JavaType.jdbcType2JavaType(jdbcType));
                    }
                    col.setComment(columnComment);
                    col.setSize(columnSize);
                    col.setDefaultValue(defaultValue);
                    col.setAutoincrement(StringUtils.equals(isAutoIncrement, "YES"));
                    col.setNullable(StringUtils.equals(isNullable, "YES"));
                    col.setDecimalDigits(decimalDigits);
                    cols.add(col);
                    LOG.debug("列:{}", col);
                }
                t.setColumns(cols);

                ResultSet primaryKeys = metaData.getPrimaryKeys(catalog, null, name);

                while (primaryKeys.next()) {
                    String columnName = primaryKeys.getString("COLUMN_NAME");
                    for (Column c : cols) {
                        if (StringUtils.equals(columnName, c.getName())) {
                            c.setPrimaryKey(true);
                            t.setPrimaryKey(c);
                        }
                    }
                }

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
        return t;
    }

}
